/*-------------------------------------------------------------------------
 - Copyright (c) 2024-2025 [XD-AMCC TEAM]
 - [XD-AMCC] is licensed under Mulan PSL v2.
 - You can use this software according to the terms and conditions of the Mulan PSL v2.
 - You may obtain a copy of Mulan PSL v2 at:
 -          http://license.coscl.org.cn/MulanPSL2
 - THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES
 - OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
 - TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 - See the Mulan PSL v2 for more details.
 ------------------------------------------------------------------------*/


/**
 * @file
 * @brief Interface of class Parser.
 *
 * @author  WXQ#XDU
 * @date    2024.11
 */

#pragma once


#ifndef AMCC_PARSER_H
#define AMCC_PARSER_H

#include "lexer.h"
#include "tree.h"

AMCC_DECL_BEGIN


/** @brief class Parser of AMCC.
 *
 * @attention  All attributes SHOULD be accessed using API below
 *             named as "parser_*()".
 */
typedef struct  parser {

    /// parse tree, the product of a parser
    t_tree_ptr          parseTree;

//private:
    t_tokenstream_ptr   tokenStream;  //!< the product of Lexer
    t_token_ptr         pNextToken;   //!< prefetched next token
    int                 nErrors;      //!< number of syntax errors

    int  indent; //!< indent to right in log file, as call-depth of RDFs
    int  maxCallDepth;   //!< max call-depth of RDFs

} t_parser, * t_parser_ptr;


// -----------------------------------------------------------------------
/// @name API of class parser
/// @{

/**
 * @brief Creates and initializes a new parser.
 * @param pTokenStream  pointer to a token stream
 * @return On success, return a pointer to new parser.
 * @return On failure, return null.
 */
extern t_parser_ptr parser_new(t_tokenstream_ptr pTokenStream);

/**
 * @brief Destroy parser and release all inner resource.
 * @param pThis    pointer to this parser
 */
extern void parser_destroy(t_parser_ptr pThis);

/**
 * @brief  Perform syntax analysis.
 *
 * @param pThis  pointer to this parser
 * @return Return 0 on success, and return negative value on failure.
 *   <br/> Return -1 on empty input;
 *   <br/> Return -2 on any syntax errors or memory allocation failures.
 */
extern int parser_run(t_parser_ptr pThis);

/**
 * @brief  Get the number of syntax errors in parsing.
 * @param pThis  pointer to this parser
 * @return the number of syntax errors(excluding bad chars, failures of file I/O).
 */
extern int parser_errors(t_parser_ptr pThis);


/**
 * @brief Get the parse tree for whole input text.
 *
 * @param pThis  pointer to the parser
 * @return Return a pointer to the parse tree for whole input text
 *   if the syntax analysis is successful, otherwise return null.
 */
t_tree_ptr parser_get_tree(t_parser_ptr pThis);

/**
 * @brief TRANSFER the ownership of tree to caller.
 *
 * @param pThis  pointer to this parser
 * @return Return the parse tree for whole input text
 *   if the syntax analysis is successful, otherwise return null.
 *
 * @warning Caller MUST destroy the tree after call this function.
 */
t_tree_ptr parser_GRAB_tree(t_parser_ptr pThis);

/// @}
// -----------------------------------------------------------------------


//
// Following macros are mainly used by Recursive-Descent-Functions
// in parser/inside/*/*.c.
// And they can also be used in other modules.
//

#define AMCC_ARG2NTID(nt)    AMCC_ARG2ID(NT_, nt )
#define AMCC_ARG2RDFID(nt)   AMCC_ARG2ID(RDF_, nt )

// make an RDF function name like RDF_*
#define RDF_function        AMCC_ARG2RDFID( THIS_NT_ID )
// make a EnumNonTerminal value like NT_*
#define THIS_NT             AMCC_ARG2NTID( THIS_NT_ID )
// make a NonTerminal name as a text
#define NT_TEXT             AMCC_ARG2STR( THIS_NT_ID )

#ifdef  THIS_NT_ID
#undef  THIS_NT_ID
#endif


AMCC_DECL_END

#endif // #ifndef AMCC_PARSER_H
